"""
在线词典服务端 逻辑处理模型
多进程tcp并发
"""
from socket import *
from multiprocessing import Process
from dict_db import *


# 具体处理客户端请求
class Handle:
    def __init__(self, conn, db):
        self.db = db  # 数据库类调用对象
        self.conn = conn  # 传入套接字
        self.name = None  # 记录名字的实例变量

    # 总体接收请求分情况讨论
    def do_request(self):
        while True:  # 循环处理请求
            request = self.conn.recv(1024).decode()
            tmp = request.split(' ')  # 解析请求类型
            if not request or tmp[0] == "E":  # 客户退出
                break  # 结束服务
            elif tmp[0] == "R":  # 注册用户
                # [R,name,passwd]
                self.do_register(tmp[1], tmp[2])  # 传入用户名密码调用函数
            elif tmp[0] == "L":  # 用户登录
                # [L,name,passwd]
                self.do_login(tmp[1], tmp[2])  # 传入用户名密码调用函数
            elif tmp[0] == "Q":  # 查询单词
                # [Q,word]
                self.do_query(tmp[1])  # 传入单词调用函数
            elif tmp[0] == "H":  # 查看历史记录
                self.do_history()  # 调用查看历史记录函数

    def do_query(self, word):  # 传入单词调用数据库方法
        # “xxxx” None
        mean = self.db.query(self.name, word)  # 传入名字和单词
        if mean:  # 如果为真
            response = "T " + mean   # 拼接响应头和解析
            self.conn.send(response.encode())  # 发送响应
        else:
            self.conn.send(b"F")

    def do_register(self, name, passwd):
        if self.db.register(name, passwd):  # 如果注册成功发送T到客户端
            self.conn.send(b"T")
        else:
            self.conn.send(b"F")

    def do_login(self, name, passwd):  # 输入用户名和密码登录
        if self.db.login(name, passwd):  # 调用数据库查询用户表中是否有该用户
            self.conn.send(b"T")
            self.name = name  # 改为实例变量值
        else:
            self.conn.send(b"F")

    def do_history(self):  # 查看历史记录
        # data-->((name,word,time),()....)
        data = self.db.history(self.name)
        if data:
            response = "T "
            for row in data:  # 遍历返回单词列表
                word = "%s,%s,%s;" % row
                response += word
            self.conn.send(response.encode())
        else:
            self.conn.send(b"F")


# 只创建进程
class DictProcess(Process):
    def __init__(self, conn):
        self.conn = conn
        self.db = DictDB()  # 连接数据库
        self.handle = Handle(conn, self.db)  # 跨类调用
        super().__init__(daemon=True)

    # 具体的进程内容
    def run(self):
        self.handle.do_request()  # 具体逻辑处理进行跨类调用
        self.conn.close()  # 关闭套接字
        self.db.close()  # 关闭数据库


# 网络服务
class DictServer:
    def __init__(self, host="", port=0):
        self.host = host
        self.port = port
        self.address = (host, port)
        self.sock = self._create_socket()

    def _create_socket(self):
        sock = socket()
        sock.bind(self.address)
        return sock

    # 启动服务 --》 客户端可以连接
    def serve_forever(self):  # 创建多进程并发模型
        self.sock.listen(5)
        print("Listen the port %d" % self.port)  # 查看连接地址
        # 循环连接客户端
        while True:
            conn, addr = self.sock.accept()  # 为每一个客户端生成套接字处理客户请求
            print("Connect from", addr)
            # 为客户端创建进程
            process = DictProcess(conn)
            process.start()


if __name__ == '__main__':
    dict = DictServer(host="0.0.0.0", port=8888)
    dict.serve_forever()  # 启动一个服务
